# coding=utf-8

from firefly.utils.singleton import Singleton
from twisted.internet import reactor
from twisted.python import log


def take_while(ls, f):
    for x in ls:
        if f(x):
            return x
    return None


class UserManager:
    __metaclass__ = Singleton

    def __init__(self):
        self._users = {}
        self._user_id = {}

    def add_user(self, user):
        """
        添加一个用户到Usermanager中
        :param user: User实例
        :return:
        """
        session_id = user.session_id
        if self.__users.has_key(session_id):
            self.drop_user_by_session_id(session_id)
        self._users[session_id] = user

        self._user_id[user.user_id] = user
        return user

    def get_user_by_session_id(self, session_id):
        """
        通过网络ID获取用户实例
        :param session_id:
        :return:
        """
        return self._users.get(session_id)

    def get_user_name_by_session_id(self, session_id):
        """
        通过网络ID获取用户姓名
        :param session_id:
        :return:
        """
        user = self.get_user_by_session_id(session_id)
        if user is not None:
            return user.username

    def get_user_id_by_session_id(self, session_id):
        """
        通过网络ID获取用户ID
        :param session_id:
        :return:
        """
        user = self.get_user_by_session_id(session_id)
        if user:
            return user.user_id

    def get_user_base_data(self, session_id):
        """
        通过网络ID获取用户基本信息
        :param session_id:
        :return:
        """
        user = self.get_user_by_session_id(session_id)
        if user:
            return {"name": user.username, "id": user.user_id}

    def get_user_by_dynamic_id(self, dynamic_id):
        """根据客户端动态ID获取user实例"""
        return take_while(self._users, lambda x: x.dynamic_id == dynamic_id)

    def get_user_by_user_id(self, user_id):
        """
        根据用户ID 获取用户信息
        :param user_id:
        :return:
        """
        return self._user_id.get(user_id)

    def get_user_by_username(self, username):
        """
        根据用户名,查找用户
        :param username:
        :return:
        """
        return take_while(self._users.values(), lambda x: x.username == username)

    def drop_user(self, user):
        """
        处理下线用户
        :param user:
        :return:
        """
        session_id = user.session_id
        log.msg("drop user user_id = %s name = %s" % (user.user_id, user.username))
        try:
            self._users.pop(session_id)
            self._user_id.pop(user.user_id)
        except Exception, e:
            print e

    def drop_user_by_user_id(self, user_id):
        """
        根据用户ID清除用户
        :param user_id:
        :return:
        """
        user = self.get_user_by_user_id(user_id)
        if user:
            self.drop_user(user)

    def drop_user_by_session_id(self, session_id):
        """
        根据网络ID清除用户
        :param session_id:
        :return:
        """
        user = self.get_user_by_session_id(session_id)
        if user:
            self.drop_user(user)

    def get_all_playing_user(self):
        """
        获取所有正在游戏的用户
        :return:
        """
        log.msg("get_all_playing_user = %s",
                [dict(x.__dict__) for x in filter(lambda x: x.is_playing, self._users.values())])
        return filter(lambda x: x.is_playing, self._users.values())

    def get_user_count(self):
        """获取在线用户"""
        return len(self._users)

    def show_current_online_player_count(self):
        player_count = self.get_user_count()
        # TODO 此处可以上报实时在线人数
        log.msg("current online player count: %s" % player_count)
        reactor.callLater(60, self.show_current_online_player_count)

    def get_user_list_keys(self):
        return self._users.keys()

    def __str__(self):
        return "".join([str(x) for x in self._users.values()])

    def get_user_list(self):
        return self._users.values()

    def user_online(self, user):
        for session, u in self._users.items():
            if u.user_id == user.user_id:
                del self._users[session]
                self.add_user(user)
                break
